home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Demos / DMBoids / boids.cpp next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  23.8 KB  |  685 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Boids.cpp
  3. //
  4. // Desc:
  5. //
  6. // Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <stdio.h>
  10. #include <math.h>
  11. #include <d3dx8.h>
  12. #include "D3DApp.h"
  13. #include "D3DFile.h"
  14. #include "D3DFont.h"
  15. #include "D3DUtil.h"
  16. #include "DXUtil.h"
  17. #include "boids.h"
  18. #include "music.h"
  19.  
  20.  
  21.  
  22.  
  23. //-----------------------------------------------------------------------------
  24. // Defines, constants, and global variables
  25. //-----------------------------------------------------------------------------
  26. BoidMusic g_Music;
  27.  
  28. struct BOIDVERTEX
  29. {
  30.     D3DXVECTOR3 p;
  31.     D3DXVECTOR3 n;
  32. };
  33.  
  34. struct GRIDVERTEX
  35. {
  36.     D3DXVECTOR3 pos;
  37.     D3DCOLOR    color;
  38. };
  39.  
  40. #define D3DFVF_BOIDVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
  41. #define D3DFVF_GRIDVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
  42.  
  43. #define NUM_BOIDS       40
  44.  
  45. inline FLOAT rnd() { return (((FLOAT)rand())/RAND_MAX); }
  46.  
  47. inline FLOAT Min( D3DXVECTOR3 v )
  48. {
  49.     if( v.x < v.y ) return (v.x < v.z ) ? v.x : v.z;
  50.     else            return (v.y < v.z ) ? v.y : v.z;
  51. }
  52.  
  53. inline FLOAT Max( D3DXVECTOR3 v )
  54. {
  55.     if( v.x > v.y ) return (v.x > v.z ) ? v.x : v.z;
  56.     else            return (v.y > v.z ) ? v.y : v.z;
  57. }
  58.  
  59. BOOL      g_bSeparation = FALSE;
  60. BOOL      g_bAlignment  = FALSE;
  61. BOOL      g_bCohesion   = FALSE;
  62. BOOL      g_bMigratory  = FALSE;
  63. BOOL      g_bObstacle   = FALSE;
  64.  
  65.  
  66.  
  67.  
  68. //-----------------------------------------------------------------------------
  69. // Name: class CMyD3DApplication
  70. // Desc: Application class. The base class (CD3DApplication) provides the 
  71. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  72. //       adds functionality specific to this sample program.
  73. //-----------------------------------------------------------------------------
  74. class CMyD3DApplication : public CD3DApplication
  75. {
  76.     CD3DFont*    m_pFont;              // Font for drawing text
  77.  
  78.     D3DXMATRIX   m_matWorld;           // Transform matrices
  79.     D3DXMATRIX   m_matView;
  80.     D3DXMATRIX   m_matProj;
  81.  
  82.     D3DLIGHT8    m_Light1;             // Lights and materials
  83.     D3DLIGHT8    m_Light2;
  84.     D3DMATERIAL8 m_mtrlBackground;
  85.     D3DMATERIAL8 m_mtrlGrid;
  86.     D3DMATERIAL8 m_mtrlBoid;
  87.  
  88.     CD3DMesh*    m_pSphere;            // Spheres
  89.     FLOAT        m_fSphereSpin;
  90.  
  91.     LPDIRECT3DVERTEXBUFFER8 m_pBoidVB; // Boid mesh
  92.     LPDIRECT3DINDEXBUFFER8  m_pBoidIB;
  93.     BOIDVERTEX   m_vBoidVertices[16];
  94.     WORD         m_wBoidIndices[30];
  95.     DWORD        m_dwNumBoidVertices;
  96.     DWORD        m_dwNumBoidIndices;
  97.  
  98.     CFlock       m_Flock;             // The flock structure
  99.  
  100.     CD3DMesh*    m_pSeaGull;          // Seagull mesh
  101.  
  102.     GRIDVERTEX   m_vGridPattern1[25]; // Grid mesh
  103.     GRIDVERTEX   m_vGridPattern2[9];
  104.  
  105.     // Internal functions
  106.     HRESULT RenderFlock();
  107.  
  108. protected:
  109.     HRESULT OneTimeSceneInit();
  110.     HRESULT InitDeviceObjects();
  111.     HRESULT RestoreDeviceObjects();
  112.     HRESULT InvalidateDeviceObjects();
  113.     HRESULT DeleteDeviceObjects();
  114.     HRESULT FinalCleanup();
  115.     HRESULT Render();
  116.     HRESULT FrameMove();
  117.  
  118. public:
  119.     LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  120.  
  121.     CMyD3DApplication();
  122. };
  123.  
  124.  
  125.  
  126.  
  127. //-----------------------------------------------------------------------------
  128. // Name: WinMain()
  129. // Desc: Entry point to the program. Initializes everything, and goes into a
  130. //       message-processing loop. Idle time is used to render the scene.
  131. //-----------------------------------------------------------------------------
  132. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  133. {
  134.     CMyD3DApplication d3dApp;
  135.  
  136.     if( FAILED( d3dApp.Create( hInst ) ) )
  137.         return 0;
  138.     return d3dApp.Run();
  139. }
  140.  
  141.  
  142.  
  143.  
  144. //-----------------------------------------------------------------------------
  145. // Name: CMyD3DApplication()
  146. // Desc: Application constructor. Sets attributes for the app.
  147. //-----------------------------------------------------------------------------
  148. CMyD3DApplication::CMyD3DApplication()
  149.                 :CD3DApplication()
  150. {
  151.     m_strWindowTitle    = _T("DMBoids: DMusic Flocking Boids Sample");
  152.     m_bUseDepthBuffer   = TRUE;
  153.  
  154.     m_fSphereSpin       = 0.0f;
  155.     m_pBoidVB           = NULL;
  156.     m_pBoidIB           = NULL;
  157.     m_pSphere           = new CD3DMesh();
  158.     m_pSeaGull          = new CD3DMesh();
  159. }
  160.  
  161.  
  162.  
  163.  
  164. //-----------------------------------------------------------------------------
  165. // Name:
  166. // Desc:
  167. //-----------------------------------------------------------------------------
  168. HRESULT CMyD3DApplication::OneTimeSceneInit()
  169. {
  170.     D3DXVECTOR3 vNorm;
  171.  
  172.     // generate the boid data
  173.     m_dwNumBoidVertices = 16;
  174.     m_dwNumBoidIndices  = 30;
  175.  
  176.     // top
  177.     m_vBoidVertices[ 0].p = D3DXVECTOR3(  0.0f, 0.0f, 10.0f); D3DXVec3Normalize( &m_vBoidVertices[ 0].n, &D3DXVECTOR3( 0.2f, 1.0f, 0.0f) );
  178.     m_vBoidVertices[ 1].p = D3DXVECTOR3( 10.0f, 0.0f,-10.0f); D3DXVec3Normalize( &m_vBoidVertices[ 1].n, &D3DXVECTOR3( 0.1f, 1.0f, 0.0f) );
  179.     m_vBoidVertices[ 2].p = D3DXVECTOR3(  3.0f, 3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[ 2].n, &D3DXVECTOR3( 0.0f, 1.0f, 0.0f) );
  180.     m_vBoidVertices[ 3].p = D3DXVECTOR3( -3.0f, 3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[ 3].n, &D3DXVECTOR3(-0.1f, 1.0f, 0.0f) );
  181.     m_vBoidVertices[ 4].p = D3DXVECTOR3(-10.0f, 0.0f,-10.0f); D3DXVec3Normalize( &m_vBoidVertices[ 4].n, &D3DXVECTOR3(-0.2f, 1.0f, 0.0f) );
  182.  
  183.     // bottom
  184.     m_vBoidVertices[ 5].p = D3DXVECTOR3(  0.0f, 0.0f, 10.0f); D3DXVec3Normalize( &m_vBoidVertices[ 5].n, &D3DXVECTOR3( 0.2f, -1.0f, 0.0f) );
  185.     m_vBoidVertices[ 6].p = D3DXVECTOR3( 10.0f, 0.0f,-10.0f); D3DXVec3Normalize( &m_vBoidVertices[ 6].n, &D3DXVECTOR3( 0.1f, -1.0f, 0.0f) );
  186.     m_vBoidVertices[ 7].p = D3DXVECTOR3(  3.0f,-3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[ 7].n, &D3DXVECTOR3( 0.0f, -1.0f, 0.0f) );
  187.     m_vBoidVertices[ 8].p = D3DXVECTOR3( -3.0f,-3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[ 8].n, &D3DXVECTOR3(-0.1f, -1.0f, 0.0f) );
  188.     m_vBoidVertices[ 9].p = D3DXVECTOR3(-10.0f, 0.0f,-10.0f); D3DXVec3Normalize( &m_vBoidVertices[ 9].n, &D3DXVECTOR3(-0.2f, -1.0f, 0.0f) );
  189.  
  190.     // rear
  191.     m_vBoidVertices[10].p = D3DXVECTOR3( 10.0f, 0.0f,-10.0f); D3DXVec3Normalize( &m_vBoidVertices[10].n, &D3DXVECTOR3(-0.4f, 0.0f, -1.0f) );
  192.     m_vBoidVertices[11].p = D3DXVECTOR3(  3.0f, 3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[11].n, &D3DXVECTOR3(-0.2f, 0.0f, -1.0f) );
  193.     m_vBoidVertices[12].p = D3DXVECTOR3( -3.0f, 3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[12].n, &D3DXVECTOR3( 0.2f, 0.0f, -1.0f) );
  194.     m_vBoidVertices[13].p = D3DXVECTOR3(-10.0f, 0.0f,-10.0f); D3DXVec3Normalize( &m_vBoidVertices[13].n, &D3DXVECTOR3( 0.4f, 0.0f, -1.0f) );
  195.     m_vBoidVertices[14].p = D3DXVECTOR3( -3.0f,-3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[14].n, &D3DXVECTOR3( 0.2f, 0.0f, -1.0f) );
  196.     m_vBoidVertices[15].p = D3DXVECTOR3(  3.0f,-3.0f, -7.0f); D3DXVec3Normalize( &m_vBoidVertices[15].n, &D3DXVECTOR3(-0.2f, 0.0f, -1.0f) );
  197.  
  198.     // top
  199.     m_wBoidIndices[ 0] = 0; m_wBoidIndices[ 1] = 1; m_wBoidIndices[ 2] = 2;
  200.     m_wBoidIndices[ 3] = 0; m_wBoidIndices[ 4] = 2; m_wBoidIndices[ 5] = 3;
  201.     m_wBoidIndices[ 6] = 0; m_wBoidIndices[ 7] = 3; m_wBoidIndices[ 8] = 4;
  202.  
  203.     // bottom
  204.     m_wBoidIndices[ 9] = 5; m_wBoidIndices[10] = 7; m_wBoidIndices[11] = 6;
  205.     m_wBoidIndices[12] = 5; m_wBoidIndices[13] = 8; m_wBoidIndices[14] = 7;
  206.     m_wBoidIndices[15] = 5; m_wBoidIndices[16] = 9; m_wBoidIndices[17] = 8;
  207.  
  208.     // rear
  209.     m_wBoidIndices[18] = 10; m_wBoidIndices[19] = 15; m_wBoidIndices[20] = 11;
  210.     m_wBoidIndices[21] = 11; m_wBoidIndices[22] = 15; m_wBoidIndices[23] = 12;
  211.     m_wBoidIndices[24] = 12; m_wBoidIndices[25] = 15; m_wBoidIndices[26] = 14;
  212.     m_wBoidIndices[27] = 12; m_wBoidIndices[28] = 14; m_wBoidIndices[29] = 13;
  213.  
  214.     // scale the boid to be unit length
  215.     for( DWORD i=0; i<16; i++ )
  216.     {
  217.         m_vBoidVertices[i].p.x /= 20.0f;
  218.         m_vBoidVertices[i].p.y /= 20.0f;
  219.         m_vBoidVertices[i].p.z /= 20.0f;
  220.     }
  221.  
  222.     // seed the random number generator
  223.     srand( timeGetTime() );
  224.  
  225.     // allocate the flock
  226.     m_Flock.m_Boids      = new Boid[NUM_BOIDS];
  227.     m_Flock.m_dwNumBoids = NUM_BOIDS;
  228.     m_Flock.m_afDist     = (FLOAT**)new LPVOID[NUM_BOIDS];
  229.     m_Flock.m_vGoal      = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  230.  
  231.     for( i=0; i<m_Flock.m_dwNumBoids; i++ )
  232.     {
  233.         D3DXMatrixIdentity( &m_Flock.m_Boids[i].matWorld );
  234.         m_Flock.m_Boids[i].vPos   = D3DXVECTOR3( 200.0f*(rnd()-rnd()), 100.0f*rnd(), 200.0f*(rnd()-rnd()) );
  235.         D3DXVec3Normalize( &m_Flock.m_Boids[i].vDir, &D3DXVECTOR3(rnd()-rnd(), rnd()-rnd(), rnd()-rnd()));
  236.         m_Flock.m_Boids[i].yaw    = 0.0f;
  237.         m_Flock.m_Boids[i].pitch  = 0.0f;
  238.         m_Flock.m_Boids[i].roll   = 0.0f;
  239.         m_Flock.m_Boids[i].dyaw   = 0.0f;
  240.         m_Flock.m_Boids[i].speed  = 0.1f;
  241.         m_Flock.m_Boids[i].color  = D3DXVECTOR3( rnd(), rnd(), rnd() );
  242.         m_Flock.m_Boids[i].color -= D3DXVECTOR3( Min(m_Flock.m_Boids[i].color), Min(m_Flock.m_Boids[i].color), Min(m_Flock.m_Boids[i].color) );
  243.         m_Flock.m_Boids[i].color /= Max( m_Flock.m_Boids[i].color );
  244.         m_Flock.m_afDist[i]       = new FLOAT[NUM_BOIDS];
  245.     }
  246.  
  247.     m_Flock.m_dwNumObstacles = 4;
  248.     m_Flock.m_Obstacles = new Obstacle[m_Flock.m_dwNumObstacles];
  249.     m_Flock.m_Obstacles[0].vPos    = D3DXVECTOR3( 100.0f, 10.0f,   0.0f );
  250.     m_Flock.m_Obstacles[1].vPos    = D3DXVECTOR3(   0.0f, 10.0f, 100.0f );
  251.     m_Flock.m_Obstacles[2].vPos    = D3DXVECTOR3(-100.0f, 10.0f,   0.0f );
  252.     m_Flock.m_Obstacles[3].vPos    = D3DXVECTOR3(   0.0f, 10.0f,-100.0f );
  253.     m_Flock.m_Obstacles[0].fRadius = 0.2f;
  254.     m_Flock.m_Obstacles[1].fRadius = 0.2f;
  255.     m_Flock.m_Obstacles[2].fRadius = 0.2f;
  256.     m_Flock.m_Obstacles[3].fRadius = 0.2f;
  257.  
  258.     D3DCOLOR diffuse  = D3DCOLOR_RGBA( 0, 0, 30, 128 );
  259.     D3DCOLOR specular = D3DCOLOR_RGBA( 0, 0, 0, 0 );
  260.  
  261.     for( i=0; i<=24; i++ )
  262.         m_vGridPattern1[i].color = diffuse;
  263.  
  264.     m_vGridPattern1[ 0].pos = D3DXVECTOR3(-25.0f, 0.0f, 35.0f );
  265.     m_vGridPattern1[ 1].pos = D3DXVECTOR3(-15.0f, 0.0f, 35.0f );
  266.     m_vGridPattern1[ 2].pos = D3DXVECTOR3( -5.0f, 0.0f, 25.0f );
  267.     m_vGridPattern1[ 3].pos = D3DXVECTOR3(  5.0f, 0.0f, 25.0f );
  268.     m_vGridPattern1[ 4].pos = D3DXVECTOR3( 15.0f, 0.0f, 35.0f );
  269.     m_vGridPattern1[ 5].pos = D3DXVECTOR3( 25.0f, 0.0f, 35.0f );
  270.     m_vGridPattern1[ 6].pos = D3DXVECTOR3( 35.0f, 0.0f, 25.0f );
  271.     m_vGridPattern1[ 7].pos = D3DXVECTOR3( 35.0f, 0.0f, 15.0f );
  272.     m_vGridPattern1[ 8].pos = D3DXVECTOR3( 25.0f, 0.0f,  5.0f );
  273.     m_vGridPattern1[ 9].pos = D3DXVECTOR3( 25.0f, 0.0f, -5.0f );
  274.     m_vGridPattern1[10].pos = D3DXVECTOR3( 35.0f, 0.0f,-15.0f );
  275.     m_vGridPattern1[11].pos = D3DXVECTOR3( 35.0f, 0.0f,-25.0f );
  276.     m_vGridPattern1[12].pos = D3DXVECTOR3( 25.0f, 0.0f,-35.0f );
  277.     m_vGridPattern1[13].pos = D3DXVECTOR3( 15.0f, 0.0f,-35.0f );
  278.     m_vGridPattern1[14].pos = D3DXVECTOR3(  5.0f, 0.0f,-25.0f );
  279.     m_vGridPattern1[15].pos = D3DXVECTOR3( -5.0f, 0.0f,-25.0f );
  280.     m_vGridPattern1[16].pos = D3DXVECTOR3(-15.0f, 0.0f,-35.0f );
  281.     m_vGridPattern1[17].pos = D3DXVECTOR3(-25.0f, 0.0f,-35.0f );
  282.     m_vGridPattern1[18].pos = D3DXVECTOR3(-35.0f, 0.0f,-25.0f );
  283.     m_vGridPattern1[19].pos = D3DXVECTOR3(-35.0f, 0.0f,-15.0f );
  284.     m_vGridPattern1[20].pos = D3DXVECTOR3(-25.0f, 0.0f, -5.0f );
  285.     m_vGridPattern1[21].pos = D3DXVECTOR3(-25.0f, 0.0f,  5.0f );
  286.     m_vGridPattern1[22].pos = D3DXVECTOR3(-35.0f, 0.0f, 15.0f );
  287.     m_vGridPattern1[23].pos = D3DXVECTOR3(-35.0f, 0.0f, 25.0f );
  288.     m_vGridPattern1[24].pos = D3DXVECTOR3(-25.0f, 0.0f, 35.0f );
  289.  
  290.     for( i=0; i<=8; i++ )
  291.         m_vGridPattern2[i].color = diffuse;
  292.  
  293.     m_vGridPattern2[0].pos = D3DXVECTOR3( -5.0f, 0.0f, 15.0f );
  294.     m_vGridPattern2[1].pos = D3DXVECTOR3(  5.0f, 0.0f, 15.0f );
  295.     m_vGridPattern2[2].pos = D3DXVECTOR3( 15.0f, 0.0f,  5.0f );
  296.     m_vGridPattern2[3].pos = D3DXVECTOR3( 15.0f, 0.0f, -5.0f );
  297.     m_vGridPattern2[4].pos = D3DXVECTOR3(  5.0f, 0.0f,-15.0f );
  298.     m_vGridPattern2[5].pos = D3DXVECTOR3( -5.0f, 0.0f,-15.0f );
  299.     m_vGridPattern2[6].pos = D3DXVECTOR3(-15.0f, 0.0f, -5.0f );
  300.     m_vGridPattern2[7].pos = D3DXVECTOR3(-15.0f, 0.0f,  5.0f );
  301.     m_vGridPattern2[8].pos = D3DXVECTOR3( -5.0f, 0.0f, 15.0f );
  302.  
  303.     if( FAILED( g_Music.LoadMusic( m_hWnd ) ) )
  304.     {
  305.         OutputDebugString("Failed to initialize DirectMusic.\n");
  306.         return E_FAIL;
  307.     }
  308.  
  309.     g_Music.StartMusic();
  310.  
  311.     return S_OK;
  312. }
  313.  
  314.  
  315.  
  316.  
  317. //-----------------------------------------------------------------------------
  318. // Name: FrameMove()
  319. // Desc:
  320. //-----------------------------------------------------------------------------
  321. HRESULT CMyD3DApplication::FrameMove()
  322. {
  323.     D3DXVECTOR3 vEyePt;
  324.     D3DXVECTOR3 vLookAtPt( 0.0f, 0.0f, 0.0f );
  325.     D3DXVECTOR3 vUp( 0.0f, 1.0f, 0.0f );
  326.  
  327.     FLOAT fTime;
  328.     FLOAT fElapsedTime;
  329.  
  330.     // The REF device is slow enough to throw off the animation
  331.     // in this sample, so if using the REF device, simulate
  332.     // running at 20fps regardless of actual rendering speed.
  333.     if( m_d3dCaps.DeviceType == D3DDEVTYPE_REF )
  334.     {
  335.         static FLOAT fTimePrev = 0.0f;
  336.         fElapsedTime = 0.05f;
  337.         fTime = fTimePrev + fElapsedTime;
  338.         fTimePrev = fTime;
  339.     }
  340.     else
  341.     {
  342.         fElapsedTime = m_fElapsedTime;
  343.         fTime = m_fTime;
  344.     }
  345.  
  346.     // Move each boids to its new location
  347.     m_Flock.Update( fElapsedTime );
  348.  
  349.     // LookAt point is the center of the flock
  350.     for( DWORD i=0; i<m_Flock.m_dwNumBoids; i++ )
  351.         vLookAtPt += m_Flock.m_Boids[i].vPos;
  352.     vLookAtPt /= (FLOAT)m_Flock.m_dwNumBoids;
  353.  
  354.     vEyePt = vLookAtPt + 40 * D3DXVECTOR3( sinf(fTime*0.111f),
  355.                                            0.70f+0.75f*sinf(fTime*0.163f),
  356.                                            cosf(fTime*0.155f) );
  357.  
  358.     D3DXMatrixLookAtLH( &m_matView, &vEyePt, &vLookAtPt, &vUp );
  359.  
  360.     g_Music.SetDistance( D3DXVec3Length( &( vEyePt - vLookAtPt ) ) );
  361.  
  362.     // Update the flock's goal
  363.     m_Flock.m_vGoal = 100.0f * D3DXVECTOR3( sinf(fTime*0.1f),  0.1f, cosf(fTime*0.1f) );
  364.  
  365.     m_fSphereSpin = fTime;
  366.  
  367.     g_Music.HandleNotifies();
  368.  
  369.     return S_OK;
  370. }
  371.  
  372.  
  373.  
  374.  
  375. //-----------------------------------------------------------------------------
  376. // Name: RenderFlock()
  377. // Desc:
  378. //-----------------------------------------------------------------------------
  379. HRESULT CMyD3DApplication::RenderFlock()
  380. {
  381.     // Set the view and projection matrices
  382.     m_pd3dDevice->SetTransform( D3DTS_VIEW,       &m_matView );
  383.     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProj );
  384.  
  385.     // Draw ground grid
  386.     m_pd3dDevice->SetMaterial( &m_mtrlGrid );
  387.  
  388.     for (int dx= -2; dx<3; dx++)
  389.     {
  390.         for (int dz= -2; dz<3; dz++)
  391.         {
  392.             D3DXMatrixTranslation( &m_matWorld, dx*80.0f, 0.0f, dz*80.0f );
  393.             m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
  394.  
  395.             m_pd3dDevice->SetVertexShader( D3DFVF_GRIDVERTEX );
  396.             m_pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, 24, m_vGridPattern1,
  397.                                            sizeof(GRIDVERTEX) );
  398.             m_pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP,  8, m_vGridPattern2,
  399.                                            sizeof(GRIDVERTEX) );
  400.         }
  401.     }
  402.  
  403.     // Draw the boids
  404.     for( DWORD i=0; i<m_Flock.m_dwNumBoids; i++ )
  405.     {
  406.         // Most of the time display the boid
  407.         if( i%13 || m_d3dCaps.DeviceType == D3DDEVTYPE_REF )
  408.         {
  409.             // Set the boid's world matrix
  410.             m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_Flock.m_Boids[i].matWorld );
  411.  
  412.             // Set the boid's color
  413.             m_mtrlBoid.Diffuse.r = m_Flock.m_Boids[i].color.x;
  414.             m_mtrlBoid.Diffuse.g = m_Flock.m_Boids[i].color.y;
  415.             m_mtrlBoid.Diffuse.b = m_Flock.m_Boids[i].color.z;
  416.             m_pd3dDevice->SetMaterial( &m_mtrlBoid );
  417.  
  418.             // Render the boid
  419.             m_pd3dDevice->SetVertexShader( D3DFVF_BOIDVERTEX );
  420.             m_pd3dDevice->SetStreamSource( 0, m_pBoidVB, sizeof(BOIDVERTEX) );
  421.             m_pd3dDevice->SetIndices( m_pBoidIB, 0L );
  422.             m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,
  423.                                                 0, m_dwNumBoidVertices,
  424.                                                 0, m_dwNumBoidIndices/3 );
  425.         }
  426.         else
  427.         {
  428.             // Set the matrix
  429.             D3DXMATRIX matWorld, matRotateY;
  430.             D3DXMatrixRotationY( &matRotateY, D3DX_PI );
  431.             D3DXMatrixMultiply( &matWorld, &matRotateY, &m_Flock.m_Boids[i].matWorld );
  432.             m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  433.  
  434.             // Display a seagull
  435.             m_pSeaGull->Render( m_pd3dDevice );
  436.         }
  437.     }
  438.  
  439.     for( i=0; i<m_Flock.m_dwNumObstacles; i++ )
  440.     {
  441.         D3DXMATRIX matRotate, matScale;
  442.         FLOAT      fScale = m_Flock.m_Obstacles[i].fRadius;
  443.         D3DXMatrixRotationY( &matRotate, m_fSphereSpin );
  444.         D3DXMatrixScaling( &matScale, fScale, fScale, fScale );
  445.         D3DXMatrixMultiply( &m_matWorld, &matScale,   &matRotate );
  446.         m_matWorld._41 = m_Flock.m_Obstacles[i].vPos.x;
  447.         m_matWorld._42 = m_Flock.m_Obstacles[i].vPos.y;
  448.         m_matWorld._43 = m_Flock.m_Obstacles[i].vPos.z;
  449.  
  450.         m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
  451.  
  452.         m_pSphere->Render( m_pd3dDevice );
  453.     }
  454.  
  455.     return S_OK;
  456. }
  457.  
  458.  
  459.  
  460.  
  461.  
  462. //-----------------------------------------------------------------------------
  463. // Name:
  464. // Desc:
  465. //-----------------------------------------------------------------------------
  466. HRESULT CMyD3DApplication::Render()
  467. {
  468.     // Clear the scene to black
  469.     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
  470.                          0x00000000, 1.0f, 0L );
  471.  
  472.     // Begin Scene
  473.     if( FAILED( m_pd3dDevice->BeginScene() ) )
  474.         return S_OK;
  475.  
  476.     RenderFlock();
  477.  
  478.     m_pd3dDevice->EndScene();
  479.  
  480.     return S_OK;
  481. }
  482.  
  483.  
  484.  
  485.  
  486. //-----------------------------------------------------------------------------
  487. // Name:
  488. // Desc:
  489. //-----------------------------------------------------------------------------
  490. HRESULT CMyD3DApplication::InitDeviceObjects()
  491. {
  492.     if( FAILED( m_pSphere->Create( m_pd3dDevice, _T("orbiter.x") ) ) )
  493.         return D3DAPPERR_MEDIANOTFOUND;
  494.     if( FAILED( m_pSeaGull->Create( m_pd3dDevice, _T("Shusui.x") ) ) )
  495.         return D3DAPPERR_MEDIANOTFOUND;
  496.  
  497.     // Create a VB for the boids
  498.     if( FAILED( m_pd3dDevice->CreateVertexBuffer( m_dwNumBoidVertices*sizeof(BOIDVERTEX),
  499.                                                   D3DUSAGE_WRITEONLY, D3DFVF_BOIDVERTEX,
  500.                                                   D3DPOOL_MANAGED, &m_pBoidVB ) ) )
  501.         return E_FAIL;
  502.  
  503.     BOIDVERTEX* v;
  504.     m_pBoidVB->Lock( 0, 0, (BYTE**)&v, 0 );
  505.     memcpy( v, m_vBoidVertices, m_dwNumBoidVertices*sizeof(BOIDVERTEX) );
  506.     m_pBoidVB->Unlock();
  507.  
  508.     // Create an IB for the boids
  509.     if( FAILED( m_pd3dDevice->CreateIndexBuffer( m_dwNumBoidIndices*sizeof(WORD),
  510.                                                  D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
  511.                                                  D3DPOOL_MANAGED, &m_pBoidIB ) ) )
  512.         return E_FAIL;
  513.  
  514.     WORD* i;
  515.     m_pBoidIB->Lock( 0, 0, (BYTE**)&i, 0 );
  516.     memcpy( i, m_wBoidIndices, m_dwNumBoidIndices*sizeof(WORD) );
  517.     m_pBoidIB->Unlock();
  518.  
  519.     return S_OK;
  520. }
  521.  
  522.  
  523.  
  524.  
  525. //-----------------------------------------------------------------------------
  526. // Name:
  527. // Desc:
  528. //-----------------------------------------------------------------------------
  529. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  530. {
  531.     m_pSphere->RestoreDeviceObjects( m_pd3dDevice );
  532.     m_pSeaGull->RestoreDeviceObjects( m_pd3dDevice );
  533.  
  534.     // Set up transform matrices
  535.     D3DXVECTOR3 vEyePt    = D3DXVECTOR3( 0.0f, 0.0f, -100.0f );
  536.     D3DXVECTOR3 vLookAtPt = D3DXVECTOR3( 0.0f, 0.0f,    0.0f );
  537.     D3DXVECTOR3 vUp       = D3DXVECTOR3( 0.0f, 1.0f,    0.0f );
  538.     D3DXMatrixIdentity( &m_matWorld );
  539.     D3DXMatrixLookAtLH( &m_matView, &vEyePt, &vLookAtPt, &vUp );
  540.     D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/4, 1.0f, 5.0f, 400.0f );
  541.  
  542.     // Setup materials
  543.     D3DUtil_InitMaterial( m_mtrlBackground, 0.0f, 0.0f, 0.0f );
  544.     D3DUtil_InitMaterial( m_mtrlGrid, 0.0f, 0.0f, 0.0f );
  545.     m_mtrlGrid.Emissive.r = 0.0f;
  546.     m_mtrlGrid.Emissive.g = 0.3f;
  547.     m_mtrlGrid.Emissive.b = 0.5f;
  548.     D3DUtil_InitMaterial( m_mtrlBoid, 1.0f, 1.0f, 1.0f );
  549.  
  550.     // Create 2 lights
  551.     D3DUtil_InitLight( m_Light1, D3DLIGHT_DIRECTIONAL, -0.5f, -1.0f, -0.3f );
  552.     D3DUtil_InitLight( m_Light2, D3DLIGHT_DIRECTIONAL,  0.5f,  1.0f,  0.3f );
  553.     m_Light2.Diffuse.r = 0.5f;
  554.     m_Light2.Diffuse.g = 0.5f;
  555.     m_Light2.Diffuse.b = 0.5f;
  556.     m_pd3dDevice->SetLight( 0, &m_Light1 );
  557.     m_pd3dDevice->SetLight( 1, &m_Light2 );
  558.     m_pd3dDevice->LightEnable( 0, TRUE );
  559.     m_pd3dDevice->LightEnable( 1, TRUE );
  560.  
  561.     // Set render state
  562.     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
  563.     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE );
  564.     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   TRUE );
  565.     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x11111111 );
  566.  
  567.     return S_OK;
  568. }
  569.  
  570.  
  571.  
  572.  
  573. //-----------------------------------------------------------------------------
  574. // Name:
  575. // Desc:
  576. //-----------------------------------------------------------------------------
  577. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  578. {
  579.     m_pSphere->InvalidateDeviceObjects();
  580.     m_pSeaGull->InvalidateDeviceObjects();
  581.  
  582.     return S_OK;
  583. }
  584.  
  585.  
  586.  
  587.  
  588. //-----------------------------------------------------------------------------
  589. // Name:
  590. // Desc:
  591. //-----------------------------------------------------------------------------
  592. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  593. {
  594.     m_pSphere->Destroy();
  595.     m_pSeaGull->Destroy();
  596.  
  597.     SAFE_RELEASE( m_pBoidVB );
  598.     SAFE_RELEASE( m_pBoidIB );
  599.  
  600.     return S_OK;
  601. }
  602.  
  603.  
  604.  
  605.  
  606. //-----------------------------------------------------------------------------
  607. // Name:
  608. // Desc:
  609. //-----------------------------------------------------------------------------
  610. HRESULT CMyD3DApplication::FinalCleanup()
  611. {
  612.     for( int i=0; i<NUM_BOIDS; i++ )
  613.     {
  614.         SAFE_DELETE_ARRAY( m_Flock.m_afDist[i] );
  615.     }
  616.  
  617.     SAFE_DELETE_ARRAY( m_Flock.m_Boids );
  618.     SAFE_DELETE_ARRAY( m_Flock.m_afDist );
  619.     SAFE_DELETE_ARRAY( m_Flock.m_Obstacles );
  620.  
  621.     SAFE_DELETE( m_pSphere );
  622.     SAFE_DELETE( m_pSeaGull );
  623.  
  624.     g_Music.EndMusic();
  625.  
  626.     return S_OK;
  627. }
  628.  
  629.  
  630.  
  631.  
  632. //-----------------------------------------------------------------------------
  633. // Name: MsgProc()
  634. // Desc: Message proc function to handle key and menu input
  635. //-----------------------------------------------------------------------------
  636. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  637.                                    LPARAM lParam )
  638. {
  639.     // Handle menu commands
  640.     if( WM_KEYDOWN==uMsg || WM_KEYUP==uMsg )
  641.     {
  642.         switch( wParam )
  643.         {
  644.         case 'A':
  645.             g_bAlignment = (WM_KEYDOWN==uMsg);
  646.             break;
  647.  
  648.         case 'C':
  649.             g_bCohesion = (WM_KEYDOWN==uMsg);
  650.             break;
  651.  
  652.         case 'O':
  653.             g_bObstacle = (WM_KEYDOWN==uMsg);
  654.             break;
  655.  
  656.         case 'M':
  657.             g_bMigratory = (WM_KEYDOWN==uMsg);
  658.  
  659.             if( g_bMigratory )
  660.                 g_Music.Migrate();
  661.             break;
  662.  
  663.         case 'S':
  664.             g_bSeparation = (WM_KEYDOWN==uMsg);
  665.  
  666.             if( g_bSeparation )
  667.                 g_Music.Collapse();
  668.             else
  669.                 g_Music.Expand();
  670.  
  671.             break;
  672.         }
  673.     }
  674.     else if( WM_ACTIVATE==uMsg )
  675.     {
  676.         g_Music.Activate( LOWORD( wParam ) != WA_INACTIVE );
  677.     }
  678.  
  679.     // Pass remaining messages to default handler
  680.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  681. }
  682.  
  683.  
  684.  
  685.